home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_emacs.idb / usr / freeware / share / emacs / 19.34 / lisp / gnus-demon.el.z / gnus-demon.el
Encoding:
Text File  |  1998-10-28  |  7.3 KB  |  223 lines

  1. ;;; gnus-demon.el --- daemonic Gnus behaviour
  2. ;; Copyright (C) 1995,96 Free Software Foundation, Inc.
  3.  
  4. ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
  5. ;; Keywords: news
  6.  
  7. ;; This file is part of GNU Emacs.
  8.  
  9. ;; GNU Emacs is free software; you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation; either version 2, or (at your option)
  12. ;; any later version.
  13.  
  14. ;; GNU Emacs is distributed in the hope that it will be useful,
  15. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. ;; GNU General Public License for more details.
  18.  
  19. ;; You should have received a copy of the GNU General Public License
  20. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  21. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  22. ;; Boston, MA 02111-1307, USA.
  23.  
  24. ;;; Commentary:
  25.  
  26. ;;; Code:
  27.  
  28. (require 'gnus)
  29.  
  30. (eval-when-compile (require 'cl))
  31.  
  32. (defvar gnus-demon-handlers nil
  33.   "Alist of daemonic handlers to be run at intervals.
  34. Each handler is a list on the form
  35.  
  36. \(FUNCTION TIME IDLE)
  37.  
  38. FUNCTION is the function to be called. 
  39. TIME is the number of `gnus-demon-timestep's between each call.  
  40. If nil, never call.  If t, call each `gnus-demon-timestep'.
  41. If IDLE is t, only call if Emacs has been idle for a while.  If IDLE
  42. is a number, only call when Emacs has been idle more than this number
  43. of `gnus-demon-timestep's.  If IDLE is nil, don't care about
  44. idleness.  If IDLE is a number and TIME is nil, then call once each
  45. time Emacs has been idle for IDLE `gnus-demon-timestep's.")
  46.  
  47. (defvar gnus-demon-timestep 60
  48.   "*Number of seconds in each demon timestep.")
  49.  
  50. ;;; Internal variables.
  51.  
  52. (defvar gnus-demon-timer nil)
  53. (defvar gnus-demon-idle-has-been-called nil)
  54. (defvar gnus-demon-idle-time 0)
  55. (defvar gnus-demon-handler-state nil)
  56. (defvar gnus-demon-is-idle nil)
  57. (defvar gnus-demon-last-keys nil) 
  58.  
  59. (eval-and-compile
  60.   (autoload 'timezone-parse-date "timezone")
  61.   (autoload 'timezone-make-arpa-date "timezone"))
  62.  
  63. ;;; Functions.
  64.  
  65. (defun gnus-demon-add-handler (function time idle)
  66.   "Add the handler FUNCTION to be run at TIME and IDLE."
  67.   ;; First remove any old handlers that use this function.
  68.   (gnus-demon-remove-handler function)
  69.   ;; Then add the new one.
  70.   (push (list function time idle) gnus-demon-handlers)
  71.   (gnus-demon-init))
  72.  
  73. (defun gnus-demon-remove-handler (function &optional no-init)
  74.   "Remove the handler FUNCTION from the list of handlers."
  75.   (setq gnus-demon-handlers 
  76.     (delq (assq function gnus-demon-handlers)
  77.           gnus-demon-handlers))
  78.   (or no-init (gnus-demon-init)))
  79.  
  80. (defun gnus-demon-init ()
  81.   "Initialize the Gnus daemon."
  82.   (interactive)
  83.   (gnus-demon-cancel)
  84.   (if (null gnus-demon-handlers)
  85.       () ; Nothing to do.
  86.     ;; Set up timer.
  87.     (setq gnus-demon-timer 
  88.       (nnheader-run-at-time 
  89.        gnus-demon-timestep gnus-demon-timestep 'gnus-demon))
  90.     ;; Reset control variables.
  91.     (setq gnus-demon-handler-state
  92.       (mapcar 
  93.        (lambda (handler)
  94.          (list (car handler) (gnus-demon-time-to-step (nth 1 handler))
  95.            (nth 2 handler)))
  96.        gnus-demon-handlers))
  97.     (setq gnus-demon-idle-time 0)
  98.     (setq gnus-demon-idle-has-been-called nil)
  99.     (setq gnus-use-demon t)))
  100.  
  101. (gnus-add-shutdown 'gnus-demon-cancel 'gnus)
  102.  
  103. (defun gnus-demon-cancel ()
  104.   "Cancel any Gnus daemons."
  105.   (interactive)
  106.   (and gnus-demon-timer
  107.        (nnheader-cancel-timer gnus-demon-timer))
  108.   (setq gnus-demon-timer nil
  109.     gnus-use-demon nil))
  110.  
  111. (defun gnus-demon-is-idle-p ()
  112.   "Whether Emacs is idle or not."
  113.   ;; We do this simply by comparing the 100 most recent keystrokes
  114.   ;; with the ones we had last time.  If they are the same, one might
  115.   ;; guess that Emacs is indeed idle.  This only makes sense if one
  116.   ;; calls this function seldom -- like once a minute, which is what
  117.   ;; we do here.
  118.   (let ((keys (recent-keys)))
  119.     (or (equal keys gnus-demon-last-keys)
  120.     (progn
  121.       (setq gnus-demon-last-keys keys)
  122.       nil))))
  123.  
  124. (defun gnus-demon-time-to-step (time)
  125.   "Find out how many seconds to TIME, which is on the form \"17:43\"."
  126.   (if (not (stringp time))
  127.       time
  128.     (let* ((date (current-time-string))
  129.        (dv (timezone-parse-date date))
  130.        (tdate (timezone-make-arpa-date 
  131.            (string-to-number (aref dv 0))
  132.            (string-to-number (aref dv 1))
  133.            (string-to-number (aref dv 2)) time
  134.            (or (aref dv 4) "UT")))
  135.        (nseconds (gnus-time-minus
  136.               (gnus-encode-date tdate) (gnus-encode-date date))))
  137.       (round
  138.        (/ (if (< nseconds 0)
  139.           (+ nseconds (* 60 60 24))
  140.         nseconds) gnus-demon-timestep)))))
  141.  
  142. (defun gnus-demon ()
  143.   "The Gnus daemon that takes care of running all Gnus handlers."
  144.   ;; Increase or reset the time Emacs has been idle.
  145.   (if (gnus-demon-is-idle-p)
  146.       (incf gnus-demon-idle-time)
  147.     (setq gnus-demon-idle-time 0)
  148.     (setq gnus-demon-idle-has-been-called nil))
  149.   ;; Then we go through all the handler and call those that are
  150.   ;; sufficiently ripe.
  151.   (let ((handlers gnus-demon-handler-state)
  152.     handler time idle)
  153.     (while handlers
  154.       (setq handler (pop handlers))
  155.       (cond 
  156.        ((numberp (setq time (nth 1 handler)))
  157.     ;; These handlers use a regular timeout mechanism.  We decrease
  158.     ;; the timer if it hasn't reached zero yet.
  159.     (or (zerop time)
  160.         (setcar (nthcdr 1 handler) (decf time)))
  161.     (and (zerop time)        ; If the timer now is zero...
  162.          (or (not (setq idle (nth 2 handler))) ; Don't care about idle.
  163.          (and (numberp idle)    ; Numerical idle...
  164.               (< idle gnus-demon-idle-time)) ; Idle timed out.
  165.          gnus-demon-is-idle)    ; Or just need to be idle.
  166.          ;; So we call the handler.
  167.          (progn
  168.            (funcall (car handler))
  169.            ;; And reset the timer.
  170.            (setcar (nthcdr 1 handler)
  171.                (gnus-demon-time-to-step
  172.             (nth 1 (assq (car handler) gnus-demon-handlers)))))))
  173.        ;; These are only supposed to be called when Emacs is idle. 
  174.        ((null (setq idle (nth 2 handler)))
  175.     ;; We do nothing.
  176.     )
  177.        ((not (numberp idle))
  178.     ;; We want to call this handler each and every time that
  179.     ;; Emacs is idle. 
  180.     (funcall (car handler)))
  181.        (t
  182.     ;; We want to call this handler only if Emacs has been idle
  183.     ;; for a specified number of timesteps.
  184.     (and (not (memq (car handler) gnus-demon-idle-has-been-called))
  185.          (< idle gnus-demon-idle-time)
  186.          (progn
  187.            (funcall (car handler))
  188.            ;; Make sure the handler won't be called once more in
  189.            ;; this idle-cycle.
  190.            (push (car handler) gnus-demon-idle-has-been-called))))))))
  191.  
  192. (defun gnus-demon-add-nocem ()
  193.   "Add daemonic NoCeM handling to Gnus."
  194.   (gnus-demon-add-handler 'gnus-demon-scan-nocem 60 t))
  195.  
  196. (defun gnus-demon-scan-nocem ()
  197.   "Scan NoCeM groups for NoCeM messages."
  198.   (gnus-nocem-scan-groups))
  199.  
  200. (defun gnus-demon-add-disconnection ()
  201.   "Add daemonic server disconnection to Gnus."
  202.   (gnus-demon-add-handler 'gnus-demon-close-connections nil 30))
  203.  
  204. (defun gnus-demon-close-connections ()
  205.   (gnus-close-backends))
  206.  
  207. (defun gnus-demon-add-scanmail ()
  208.   "Add daemonic scanning of mail from the mail backends."
  209.   (gnus-demon-add-handler 'gnus-demon-scan-mail 120 60))
  210.  
  211. (defun gnus-demon-scan-mail ()
  212.   (let ((servers gnus-opened-servers)
  213.     server)
  214.     (while (setq server (car (pop servers)))
  215.       (and (gnus-check-backend-function 'request-scan (car server))
  216.        (or (gnus-server-opened server)
  217.            (gnus-open-server server))
  218.        (gnus-request-scan nil server)))))
  219.  
  220. (provide 'gnus-demon)
  221.  
  222. ;;; gnus-demon.el ends here
  223.